package view;

import javax.swing.*;
import javax.swing.text.DefaultCaret;

import builder.*;

import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;

import model.*;

/**
 * 
 * This is the main GUI for the application. 
 * @author Roman Pusec, Dennis Goldfinger, Marko Bilic
 *
 */
@SuppressWarnings("serial")
public class GUI extends JFrame implements ActionListener, common.IObserver
{
	private JMenuBar menuBar;
	private JMenu mainMenu, foodMenu;
	private JMenuItem 	saveBtn, addFoodFrameBtn, addRecipeFrameBtn, exitBtn,
						exerciseMenu, addExerciseFrameBtn, addWorkoutFrameBtn;
	private JButton viewBtn, editBtn, cancelBtn, addRecipeBtn, addFoodBtn, saveLogBtn, viewChartBtn, viewExportBtn,
					jbAddFoodLog, jbRemoveFoodLog, jbAddRecipeLog, addIngredientBtn, viewEditBtn, viewBackBtn, cancelRecipeBtn,
					jbAddExerciseLog, jbAddWorkoutLog, jbRemoveExerciseLog, addExerciseBtn,
					addWorkoutBtn, addExerciseWorkoutFrameBtn, cancelWorkoutFrameBtn;
	private JPanel 	cardPanel, mainPanel, editPanel, viewPanel, 
					editSouth, viewNorth;
	private JTabbedPane editNorth;
	private CardLayout cardLayout;
	private JTextField 	jtfRecipeName, jtfFoodName, jtfFoodCalories, jtfFoodProtein, jtfFoodFat,  
						jtfFoodCarbs, jtfFoodQuantity, jtfRecipeQuantity, jtfIngredientQuantity,
						jtfWeight, jtfCal,
						jtfExerciseQuantityLog, jtfWorkoutQuantityLog, jtfExerciseFrameName, jtfExerciseFrameExp,
						jtfWorkoutFrameName, jtfWrokoutFrExerQuantity;
	private JComboBox 	cbRemoveFoodLog, cbFoodNameLog, cbRecipeNameLog, cbAddRecipe,
						cbExerciseNameLog, cbWorkoutNameLog, cbRemoveExerciseLog, cbAddWorkout;
	private JTextArea jtaDisplayDailyLog, jtaRecipeIngredients, jtaWorkoutFrameExercises;
	private JFrame recipeFrame, foodFrame, exerciseFrame, workoutFrame;
	private Cal calendar = new Cal();
	private controller.Controller controller;
	private Recipe newRecipe;
	private Workout newWorkout;
	
	/**
	 * Constructs the GUI. 
	 */
	public GUI()
	{
		//set frame properties
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setTitle("Diet Manager");
		setSize(600,350);
		setMinimumSize(new Dimension(600, 350));
		setLayout(new BorderLayout());
		setLocationRelativeTo(null);
		
		createMenu();
		
		//create the GUI buttons
		viewBtn = new JButton("View");
		editBtn = new JButton("Edit");
		cancelBtn = new JButton("Cancel");
		saveLogBtn = new JButton("Save");
		
		//set up the card layout
		cardLayout = new CardLayout();
		cardPanel = new JPanel();
		cardPanel.setLayout(cardLayout);
		
		//set up CardLayout panels (or "cards")
		mainPanel = new JPanel();
		mainPanel.setLayout(new BorderLayout());
		editPanel = new JPanel();
		editPanel.setLayout(new BorderLayout());
		viewPanel = new JPanel();
		viewPanel.setLayout(new BorderLayout());
		
		//methods that build the content of edit panel and view panel
		buildEditPanel();
		buildViewPanel();
		
		//set up panel 1 sub panels
		JPanel mainPanelBtns = new JPanel();
		JPanel mainPanelCal = new JPanel();
		
		//add the buttons and the panel 1 sub panels
		mainPanelBtns.add(new JLabel("Select a date and then choose to"));
		mainPanelBtns.add(viewBtn);
		mainPanelBtns.add(new JLabel("or"));
		mainPanelBtns.add(editBtn);
		mainPanelBtns.add(new JLabel("your daily log."));
		
		//add the calendar to the appropriate sub panel
		mainPanelCal.add(calendar);
		
		//add button sub panel to panel 1
		mainPanel.add(mainPanelBtns, "North");
		mainPanel.add(mainPanelCal, "Center");
				
		//add the layout panels to the main GUI panel with the card layout
		cardPanel.add(mainPanel, "mainCard");
		cardPanel.add(editPanel, "editCard");
		cardPanel.add(viewPanel, "viewCard");
				
		add(cardPanel);
		
		//add event listeners to the buttons
		editBtn.addActionListener(this);
		viewBtn.addActionListener(this);
		cancelBtn.addActionListener(this);
		addFoodFrameBtn.addActionListener(this);
		addRecipeFrameBtn.addActionListener(this);
		addExerciseFrameBtn.addActionListener(this);
		addWorkoutFrameBtn.addActionListener(this);
		saveBtn.addActionListener(this);
		exitBtn.addActionListener(this);
		saveLogBtn.addActionListener(this);
		jbAddFoodLog.addActionListener(this);
		jbRemoveFoodLog.addActionListener(this);
		jbRemoveExerciseLog.addActionListener(this); 
		jbAddRecipeLog.addActionListener(this);
		jbAddExerciseLog.addActionListener(this);
		jbAddWorkoutLog.addActionListener(this);
		viewChartBtn.addActionListener(this);
		
		setVisible(true);
		
		controller = new controller.Controller("src/xml/daily_log.xml", "src/xml/basic.xml", "src/xml/recipe.xml", "src/xml/exercise.xml", "src/xml/workout.xml");
		controller.subscribe(this);
	}
	
	@Override
	public void actionPerformed(ActionEvent e) 
	{
		if(e.getSource() == cancelBtn || e.getSource() == viewBackBtn)
		{
			// switch back to main card and cancel current log modifications
			cardLayout.show(cardPanel, "mainCard");
			setSize(getMinimumSize());
			controller.cancelCurrentLog();
		}
		else if(e.getSource() == cancelRecipeBtn)
		{
			// close recipe frame if open
			if(recipeFrame != null)
				recipeFrame.dispose();
		}
		else if(e.getSource() == editBtn || e.getSource() == viewEditBtn)
		{
			// switch to edit card to edit current daily log entry
			controller.selectDate(calendar.getCurrentDate());
			cardLayout.show(cardPanel, "editCard");
			setSize(new Dimension(getMinimumSize().width, 750));
			pack();
		}
		else if(e.getSource() == viewBtn)
		{
			// switch to view card to display current daily log entry details
			controller.selectDate(calendar.getCurrentDate());
			cardLayout.show(cardPanel, "viewCard");
			setSize(getMinimumSize());
		}
		else if(e.getSource() == viewChartBtn)
		{
			// get calorie data from controller
			double fatAmount = controller.getTotalFatCalories();
			double carbsAmount = controller.getTotalCarbCalories();
			double proteinAmount = controller.getTotalProteinCalories();
			
			if(fatAmount + carbsAmount + proteinAmount == 0)
			{
				JOptionPane.showMessageDialog(this, "There is no chart available for today. Check if you have entered your intake properly.");
			}
			else
			{
				// show pie chart of calories in current daily log intake
				new DailyLogChart(fatAmount, carbsAmount, proteinAmount);
			}
		}
		else if(e.getSource() == viewExportBtn)
		{
			Object[] options = {"Cancel", "CSV", "JSON"};
			int n = JOptionPane.showOptionDialog(this,
				"How would you like your daily logs exported?",
				"Export",
				JOptionPane.YES_NO_OPTION,
				JOptionPane.QUESTION_MESSAGE,
				null,     //do not use a custom Icon
				options,  //the titles of buttons
				options[0]); //default button title
			
			String fileName = "";
			
			// User selected "cancel"
			if(n == 0)
			{
				return; // end method execution
			}
			// User selected "CSV"
			else if(n == 1)
			{
				controller.setFileBuilder(new CSVBuilder());
				fileName = "daily_logs.csv";
			}
			// User selected "JSON"
			else if(n == 2)
			{
				controller.setFileBuilder(new JSONBuilder());
				fileName = "daily_logs.json";
			}
			
			FileDialog fDialog = new FileDialog(this, "Save", FileDialog.SAVE);
			fDialog.setFile(fileName);
	        fDialog.setVisible(true);
	        String path = fDialog.getDirectory() + fDialog.getFile();
	        File f = new File(path);
	        try {
	        	
	        	// Create new file if it doesn't already exist
	        	f.createNewFile();
	        	
				// Write to file (WILL OVERWRITE)
	        	PrintWriter writer = new PrintWriter(path, "UTF-8");
				writer.println(controller.buildFile());
				writer.close();
				
				JOptionPane.showMessageDialog(this, "File saved successfully.");
			} catch (IOException e1) {
				e1.printStackTrace();
				JOptionPane.showMessageDialog(this, "File save failed.");
			}
		}
		else if(e.getSource() == exitBtn)
		{
			// attempt to save and contents to xml
			try {
				controller.saveChanges();
			} catch (Exception e1) {
				System.out.println("Something went wrong! Hit the decks laddies!");
				JOptionPane.showMessageDialog(this, "Oh no, something seems to have gone terribly wrong! Try again!");
				cardLayout.show(cardPanel, "mainCard");
				setSize(getMinimumSize());
			}
			System.exit(getDefaultCloseOperation());
		}
		else if(e.getSource() == addRecipeFrameBtn)
		{
			// prepare and open add recipe frame
			newRecipe = new Recipe("Default Recipe");
			addRecipeFrame();
		}
		else if(e.getSource() == addFoodFrameBtn)
		{
			// open add food frame
			addFoodFrame();
		}
		else if(e.getSource() == addFoodBtn)
		{
			// get details from frame
			String name = jtfFoodName.getText();
			
			double calories = 0.00;
			double protein = 0.00;
			double fat = 0.00;
			double carbs = 0.00;
			
			// handle number format exceptions
			try{
				calories = Double.parseDouble(jtfFoodCalories.getText());
				protein = Double.parseDouble(jtfFoodProtein.getText());
				fat = Double.parseDouble(jtfFoodFat.getText());
				carbs = Double.parseDouble(jtfFoodCarbs.getText());
			}
			catch(NumberFormatException nfe)
			{
				JOptionPane.showMessageDialog(foodFrame, "One or more fields contain invalid data!");
				return;
			}
			
			// Percentages must add up to 100
			if((protein + fat + carbs) != 100)
			{
				JOptionPane.showMessageDialog(foodFrame, "Percentage protein, fat, and carbs must add up to 100");
				return;
			}
			
			// check if name field is empty or contains quotes/commas
			if(name.equals("") || hasCommasOrQuotes(name))
			{
				JOptionPane.showMessageDialog(foodFrame, "The food name cannot be empty or contain commas or quotes.");
			}
			else {
				// create new food based on details
				Basic newFood = new Basic(name, calories, protein, fat, carbs);
				controller.addFood(newFood);
				JOptionPane.showMessageDialog(foodFrame, "New basic food added successfully!");
				foodFrame.dispose();
			}
		}
		else if(e.getSource() == addIngredientBtn)
		{
			String ingredient = (String)cbAddRecipe.getSelectedItem();
			int quantity = Integer.parseInt(jtfIngredientQuantity.getText());
			
			// add ingredient to recipe
			newRecipe.addFood(new Food(ingredient), quantity);
			
			if(!jtfRecipeName.getText().equals(""))
			{
				newRecipe.setName(jtfRecipeName.getText());
			}
			
			// update current new recipe in editor
			jtaRecipeIngredients.setText("New Recipe:\n" + newRecipe.toString());
		}
		else if(e.getSource() == addRecipeBtn)
		{
			String name = jtfRecipeName.getText();
			
			// check if name contains quotes/commas
			if(name.indexOf(",") != -1 || name.indexOf("\"") != -1)
			{
				JOptionPane.showMessageDialog(foodFrame, "The recipe name cannot contain commas or quotes.");
			}
			else {
				newRecipe.setName(name);
				
				// add new recipe once finished
				controller.addFood(newRecipe);
				JOptionPane.showMessageDialog(recipeFrame, "New recipe added successfully!");
				recipeFrame.dispose();
			}
		}
		else if(e.getSource() == saveBtn)
		{
			// attempt to save and contents to xml
			try {
				controller.saveChanges();
				JOptionPane.showMessageDialog(this, "Everything saved successfully");
				cardLayout.show(cardPanel, "mainCard");
				setSize(getMinimumSize());
			} catch (Exception e1) {
				System.out.println("Something went wrong! Hit the decks laddies!");
				JOptionPane.showMessageDialog(this, "Oh no, something seems to have gone terribly wrong! Try again!");
				cardLayout.show(cardPanel, "mainCard");
				setSize(getMinimumSize());
			}
		}
		else if(e.getSource() == jbAddFoodLog)
		{
			// add food to log intake
			controller.addFoodToLog(new Food((String) cbFoodNameLog.getSelectedItem()), Integer.parseInt(jtfFoodQuantity.getText()));
			JOptionPane.showMessageDialog(this, (String) cbFoodNameLog.getSelectedItem() + " added to intake!");
		}
		else if(e.getSource() == jbAddRecipeLog)
		{
			// add recipe to log intake
			controller.addFoodToLog(new Food((String) cbRecipeNameLog.getSelectedItem()), Integer.parseInt(jtfRecipeQuantity.getText()));
			JOptionPane.showMessageDialog(this, (String) cbRecipeNameLog.getSelectedItem() + " added to intake!");
		}
		else if(e.getSource() == saveLogBtn)
		{
			// attempt to save and contents to xml
			try {
				controller.changeCalorieLimit(Double.parseDouble(jtfCal.getText()));
				controller.changeWeight(Double.parseDouble(jtfWeight.getText()));
				controller.saveChanges();
				JOptionPane.showMessageDialog(this, "Daily log saved successfully");
				cardLayout.show(cardPanel, "viewCard");
				setSize(getMinimumSize());
				setLocationRelativeTo(null); 
			} catch (Exception e1) {
				System.out.println("Something went wrong! Hit the decks laddies!");
				JOptionPane.showMessageDialog(this, "Oh no, something seems to have gone terribly wrong! Try again!");
				cardLayout.show(cardPanel, "mainCard");
				setSize(getMinimumSize());
			}
		}
		else if(e.getSource() == jbRemoveFoodLog)
		{
			// remove food from intake
			controller.deleteFoodFromLog((Food) cbRemoveFoodLog.getSelectedItem());
		}
		else if(e.getSource() == addExerciseFrameBtn)
		{
			//opens the exercise frame
			addExerciseFrame();
		}
		else if(e.getSource() == addExerciseBtn)
		{
			String name = jtfExerciseFrameName.getText();
			
			//hasCommasOrQuotes(String input)
			
			if(hasCommasOrQuotes(name))
			{
				JOptionPane.showMessageDialog(foodFrame, "The exercise name cannot contain commas or quotes.");
			}
			else
			{
				try {
					Exercise newExercise = new Exercise(jtfExerciseFrameName.getText(), Double.parseDouble(jtfExerciseFrameExp.getText()));
					controller.addExercise(newExercise);
					JOptionPane.showMessageDialog(exerciseFrame, "Exercise successfully saved! ");
					exerciseFrame.dispose();
				} catch (NumberFormatException nfe) {
					JOptionPane.showMessageDialog(exerciseFrame, "Please enter a number for the calorie expenditure. "); 
					return;
				}
			}
		}
		else if(e.getSource() == addWorkoutFrameBtn)
		{
			newWorkout = new Workout("Default Workout");
			addWorkoutFrame();
		}
		else if(e.getSource() == addExerciseWorkoutFrameBtn)
		{
			String chosenActivity = (String) cbAddWorkout.getSelectedItem();
			
			try 
			{
				newWorkout.addExercise(new Activity(chosenActivity), Integer.parseInt(jtfWrokoutFrExerQuantity.getText()));
				
				if(newWorkout.getName() != "")
				{
					newWorkout.setName(jtfWorkoutFrameName.getText());
				}
				
				jtaWorkoutFrameExercises.setText(newWorkout.toString());
			} 
			catch (NumberFormatException nfe) {
				JOptionPane.showMessageDialog(exerciseFrame, "Please enter a number for the quantity. ");
				return;
			}
		}
		else if(e.getSource() == addWorkoutBtn)
		{
			String name = jtfWorkoutFrameName.getText();
			
			if(hasCommasOrQuotes(name))
			{
				JOptionPane.showMessageDialog(workoutFrame, "The Workout name cannot contain commas or quotes.");
			}
			else
			{
				newWorkout.setName(jtfWorkoutFrameName.getText());
				controller.addExercise(newWorkout);
				JOptionPane.showMessageDialog(workoutFrame, "Workout successfully added! ");
				workoutFrame.dispose();
				newWorkout = null;
			}
		}
		else if(e.getSource() == jbAddExerciseLog)
		{
			try {
				controller.addExerciseToLog(new Activity((String) cbExerciseNameLog.getSelectedItem()), Integer.parseInt(jtfExerciseQuantityLog.getText()));
				JOptionPane.showMessageDialog(null, "Exercise successfully added! ");
			} catch (NumberFormatException nfe) {
				JOptionPane.showMessageDialog(null, "Please enter a number for the quantity. ");
			}
		}
		else if(e.getSource() == jbAddWorkoutLog)
		{
			try {
				controller.addExerciseToLog(new Activity((String) cbWorkoutNameLog.getSelectedItem()), Integer.parseInt(jtfWorkoutQuantityLog.getText()));
				JOptionPane.showMessageDialog(null, "Workout successfully added! ");
			} catch (NumberFormatException nfe) {
				JOptionPane.showMessageDialog(null, "Please enter a number for the quantity. ");
			}
		}
		else if(e.getSource() == jbRemoveExerciseLog)
		{
			controller.deleteExerciseFromLog((Activity) cbRemoveExerciseLog.getSelectedItem());
		}
	}
	
	/**
	 * Creates the menu. 
	 */
	private void createMenu()
	{
		//create a new menu bar and add a menu called "File"
		menuBar = new JMenuBar();
		mainMenu = new JMenu("File");
		foodMenu = new JMenu("Food List");
		exerciseMenu = new JMenu("Activity List");
		
		//create menu buttons and add them to the menu
		saveBtn = new JMenuItem("Save");
		exitBtn = new JMenuItem("Exit");
		addFoodFrameBtn = new JMenuItem("Add Food");
		addRecipeFrameBtn = new JMenuItem("Add Recipe");
		addExerciseFrameBtn = new JMenuItem("Add Exercise");
		addWorkoutFrameBtn = new JMenuItem("Add Workout");
		
		mainMenu.add(saveBtn);
		mainMenu.add(exitBtn);
		foodMenu.add(addFoodFrameBtn);
		foodMenu.add(addRecipeFrameBtn);
		exerciseMenu.add(addExerciseFrameBtn);
		exerciseMenu.add(addWorkoutFrameBtn);
		
		//add the menu to the menu bar and set it to the main frame
		menuBar.add(mainMenu);
		menuBar.add(foodMenu);
		menuBar.add(exerciseMenu);
		setJMenuBar(menuBar);
	}
	
	/**
	 * Creates the Recipe frame, and the clients can add their own Recipes. 
	 */
	private void addRecipeFrame()
	{
		recipeFrame = new JFrame("Add recipe window");
		recipeFrame.setSize(450,400);
		recipeFrame.setLocationRelativeTo(null);
		recipeFrame.setLayout(new BorderLayout());
		
		JPanel recipeNorth = new JPanel();
		recipeNorth.setLayout(new BorderLayout());
		recipeNorth.setBorder(BorderFactory.createTitledBorder("Add info"));
		JPanel ingredientsPanel = new JPanel();
		ingredientsPanel.setBorder(BorderFactory.createTitledBorder("Add ingredients"));
		JPanel recipeNamePanel = new JPanel();
		recipeNamePanel.setBorder(BorderFactory.createTitledBorder("Recipe name"));
		JPanel recipeTextPanel = new JPanel();
		JPanel recipeSouth = new JPanel();
		
		jtfRecipeName = new JTextField(10);
		jtfIngredientQuantity = new JTextField(2);
		
		addRecipeBtn = new JButton("Add recipe");
		addRecipeBtn.addActionListener(this);
		addIngredientBtn = new JButton("Add");
		addIngredientBtn.addActionListener(this);
		cancelRecipeBtn = new JButton("Cancel");
		cancelRecipeBtn.addActionListener(this);
		
		ArrayList<String> data = new ArrayList<String>();
		
		//getting the names of foods
		for(int i = 0; i < controller.getBasicList().size(); i++)
			data.add(controller.getBasicList().get(i).getName());
		
		//getting the names of recipes
		for(int i = 0; i < controller.getRecipeList().size(); i++)
			data.add(controller.getRecipeList().get(i).getName());
		
		cbAddRecipe = new JComboBox(data.toArray());
		
		jtaRecipeIngredients = new JTextArea(10, 30);
		jtaRecipeIngredients.setWrapStyleWord(true);
		jtaRecipeIngredients.setEditable(false);
		jtaRecipeIngredients.setDisabledTextColor(Color.BLACK);
		
		JScrollPane jsp = new JScrollPane(jtaRecipeIngredients);
		DefaultCaret caret = (DefaultCaret)jtaRecipeIngredients.getCaret();
		caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
		
		ingredientsPanel.add(cbAddRecipe);
		ingredientsPanel.add(new JLabel("#: "));
		ingredientsPanel.add(jtfIngredientQuantity);
		ingredientsPanel.add(addIngredientBtn);
		
		recipeNamePanel.add(jtfRecipeName);
		recipeTextPanel.add(jsp);
		
		recipeNorth.add(recipeNamePanel, "North");
		recipeNorth.add(ingredientsPanel, "South");
		recipeSouth.add(addRecipeBtn);
		recipeSouth.add(cancelRecipeBtn);
		
		recipeFrame.add(recipeNorth, "North");
		recipeFrame.add(recipeTextPanel, "Center");
		recipeFrame.add(recipeSouth, "South");
		
		recipeFrame.setResizable(false);
		recipeFrame.setVisible(true);
	}
	
	/**
	 * Creates the Food frame, and the clients can add their own Foods. 
	 */
	private void addFoodFrame()
	{
		foodFrame = new JFrame("Add food window");
		foodFrame.setSize(300,250);
		foodFrame.setLocationRelativeTo(null);
		foodFrame.setLayout(new BorderLayout());
		
		JPanel foodNorth = new JPanel();
		foodNorth.setLayout(new GridLayout(5,1));
		foodNorth.setBorder(BorderFactory.createTitledBorder("Add info"));
		JPanel foodSouth = new JPanel();
		
		jtfFoodName 	= new JTextField(10);
		jtfFoodCalories = new JTextField(10);
		jtfFoodProtein 	= new JTextField(10);
		jtfFoodFat 		= new JTextField(10);
		jtfFoodCarbs 	= new JTextField(10);
		
		addFoodBtn = new JButton("Add");
		addFoodBtn.addActionListener(this);
		
		foodNorth.add(new JLabel("Name: "));
		foodNorth.add(jtfFoodName);
		foodNorth.add(new JLabel("Calories: "));
		foodNorth.add(jtfFoodCalories);
		foodNorth.add(new JLabel("Fat (%): "));
		foodNorth.add(jtfFoodFat);
		foodNorth.add(new JLabel("Protein (%): "));
		foodNorth.add(jtfFoodProtein);
		foodNorth.add(new JLabel("Carbs (%): "));
		foodNorth.add(jtfFoodCarbs);
		foodSouth.add(addFoodBtn);
		
		foodFrame.add(foodNorth, "North");
		foodFrame.add(foodSouth, "South");
		
		foodFrame.setResizable(false);
		foodFrame.setVisible(true);
	}
	
	/**
	 * Creates the Exercise frame, and the clients can add their own Exercises. 
	 */
	private void addExerciseFrame()
	{
		exerciseFrame = new JFrame("Add exercise window");
		exerciseFrame.setSize(300,250);
		exerciseFrame.setLocationRelativeTo(null);
		exerciseFrame.setLayout(new BorderLayout());
		
		JPanel exerciseNorth = new JPanel();
		exerciseNorth.setLayout(new GridLayout(2,1));
		exerciseNorth.setBorder(BorderFactory.createTitledBorder("Add info"));
		JPanel exerciseSouth = new JPanel();
		
		jtfExerciseFrameName = new JTextField(10); 
		jtfExerciseFrameExp = new JTextField(10);
		
		addExerciseBtn = new JButton("Add");
		addExerciseBtn.addActionListener(this);
		
		exerciseNorth.add(new JLabel("Name: "));
		exerciseNorth.add(jtfExerciseFrameName);
		exerciseNorth.add(new JLabel("Caloric Expenditure: "));
		exerciseNorth.add(jtfExerciseFrameExp);
		exerciseSouth.add(addExerciseBtn);
		
		exerciseFrame.add(exerciseNorth, "North");
		exerciseFrame.add(exerciseSouth, "South");
		
		exerciseFrame.setResizable(false);
		exerciseFrame.setVisible(true);
	}
	
	/**
	 * Creates the Workout frame, and the clients can add their own Workouts. 
	 */
	private void addWorkoutFrame()
	{
		workoutFrame = new JFrame("Add workout window");
		workoutFrame.setSize(450,400);
		workoutFrame.setLocationRelativeTo(null);
		workoutFrame.setLayout(new BorderLayout());
		
		JPanel workoutNorth = new JPanel();
		workoutNorth.setLayout(new BorderLayout());
		workoutNorth.setBorder(BorderFactory.createTitledBorder("Add info"));
		JPanel exercisesPanel = new JPanel();
		exercisesPanel.setBorder(BorderFactory.createTitledBorder("Add exercises"));
		JPanel workoutNamePanel = new JPanel();
		workoutNamePanel.setBorder(BorderFactory.createTitledBorder("Workout name"));
		JPanel workoutTextPanel = new JPanel();
		JPanel workoutSouth = new JPanel();
		
		jtfWorkoutFrameName = new JTextField(10);
		jtfWrokoutFrExerQuantity = new JTextField(2); 
		
		addWorkoutBtn = new JButton("Add workout");
		addWorkoutBtn.addActionListener(this);
		addExerciseWorkoutFrameBtn = new JButton("Add");
		addExerciseWorkoutFrameBtn.addActionListener(this);
		cancelWorkoutFrameBtn = new JButton("Cancel");
		cancelWorkoutFrameBtn.addActionListener(this);
		
		ArrayList<String> data = new ArrayList<String>();
		
		//getting the names of exercises
		for(int i = 0; i < controller.getBasicExerciseList().size(); i++)
			data.add(controller.getBasicExerciseList().get(i).getName());
		
		//getting the names of workouts
		for(int i = 0; i < controller.getWorkoutList().size(); i++)
			data.add(controller.getWorkoutList().get(i).getName());
		
		cbAddWorkout = new JComboBox(data.toArray());
		
		jtaWorkoutFrameExercises = new JTextArea(10, 30);
		jtaWorkoutFrameExercises.setWrapStyleWord(true);
		jtaWorkoutFrameExercises.setEditable(false);
		jtaWorkoutFrameExercises.setDisabledTextColor(Color.BLACK);
		
		JScrollPane jsp = new JScrollPane(jtaWorkoutFrameExercises);
		DefaultCaret caret = (DefaultCaret)jtaWorkoutFrameExercises.getCaret();
		caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
		
		exercisesPanel.add(cbAddWorkout);
		exercisesPanel.add(new JLabel("#: "));
		exercisesPanel.add(jtfWrokoutFrExerQuantity);
		exercisesPanel.add(addExerciseWorkoutFrameBtn);
		
		workoutNamePanel.add(jtfWorkoutFrameName);
		workoutTextPanel.add(jsp);
		
		workoutNorth.add(workoutNamePanel, "North");
		workoutNorth.add(exercisesPanel, "South");
		workoutSouth.add(addWorkoutBtn);
		workoutSouth.add(cancelWorkoutFrameBtn);
		
		workoutFrame.add(workoutNorth, "North");
		workoutFrame.add(workoutTextPanel, "Center");
		workoutFrame.add(workoutSouth, "South");
		
		workoutFrame.setResizable(false);
		workoutFrame.setVisible(true);
	}
	
	/**
	 * Builds the Edit panel. 
	 */
	private void buildEditPanel()
	{
		//Initial container
		JPanel editInitial = 			new JPanel();
		
		//Sub-containers
		JPanel jpEditFood = 			new JPanel();
		JPanel jpEditExercises = 		new JPanel();
		
		//Sub-sub-containers
		JPanel editAddFood = 			new JPanel();
		JPanel editDeleteFood = 		new JPanel();
		JPanel editAddExercises = 		new JPanel();
		JPanel editDeleteExercises = 	new JPanel();
		
		//Main containers
		editNorth = 					new JTabbedPane();
		editSouth = 					new JPanel();
		editNorth.setBorder(BorderFactory.createTitledBorder("Daily Log"));
		
		jtfWeight = new JTextField();
		jtfCal = new JTextField();
		
		//setting up initial info JPanel
		editInitial.setLayout(new GridLayout(2,1));
		editInitial.setBorder(BorderFactory.createTitledBorder("Initial info"));
		editInitial.add(new JLabel("Weight: "));
		editInitial.add(jtfWeight);
		editInitial.add(new JLabel("Calorie limit: "));
		editInitial.add(jtfCal);
		
		// -- Food/Recipes --
		jpEditFood.setLayout(new BorderLayout());
		jpEditFood.setBorder(BorderFactory.createTitledBorder("Food/Recipe"));
		
		editAddFood.setLayout(new GridLayout(6,2));
		editAddFood.setBorder(BorderFactory.createTitledBorder("Add to intake"));
		
		editDeleteFood.setBorder(BorderFactory.createTitledBorder("Delete from intake"));
		
		// -- Exercises/Workouts --
		jpEditExercises.setLayout(new BorderLayout());
		jpEditExercises.setBorder(BorderFactory.createTitledBorder("Exercises/Workouts"));
		
		editAddExercises.setLayout(new GridLayout(6,2));
		editAddExercises.setBorder(BorderFactory.createTitledBorder("Add to exercises"));
		
		editDeleteExercises.setBorder(BorderFactory.createTitledBorder("Delete from exercises"));
		
		// -- Food/Recipes --
		cbFoodNameLog 			= new JComboBox();
		jtfFoodQuantity 		= new JTextField();
		jbAddFoodLog			= new JButton("Add food to Log");
		cbRecipeNameLog 		= new JComboBox();
		jtfRecipeQuantity 		= new JTextField();
		jbAddRecipeLog			= new JButton("Add recipe to Log");
		
		// -- Exercises/Workouts --
		cbExerciseNameLog 		= new JComboBox();
		jtfExerciseQuantityLog 	= new JTextField();
		jbAddExerciseLog		= new JButton("Add exercise to Log");
		cbWorkoutNameLog 		= new JComboBox();
		jtfWorkoutQuantityLog 	= new JTextField();
		jbAddWorkoutLog			= new JButton("Add workout to Log");
		
		// -- Food/Recipes --
		editAddFood.add(new JLabel("Food: "));
		editAddFood.add(cbFoodNameLog);
		editAddFood.add(new JLabel("Quantity: "));
		editAddFood.add(jtfFoodQuantity);
		editAddFood.add(new JLabel());
		editAddFood.add(jbAddFoodLog);
		editAddFood.add(new JLabel("Recipe: "));
		editAddFood.add(cbRecipeNameLog);
		editAddFood.add(new JLabel("Quantity: "));
		editAddFood.add(jtfRecipeQuantity);
		editAddFood.add(new JLabel());
		editAddFood.add(jbAddRecipeLog);
		
		// -- Exercises/Workouts --
		editAddExercises.add(new JLabel("Exercise: "));
		editAddExercises.add(cbExerciseNameLog);
		editAddExercises.add(new JLabel("Quantity: "));
		editAddExercises.add(jtfExerciseQuantityLog);
		editAddExercises.add(new JLabel());
		editAddExercises.add(jbAddExerciseLog);
		editAddExercises.add(new JLabel("Workout: "));
		editAddExercises.add(cbWorkoutNameLog);
		editAddExercises.add(new JLabel("Quantity: "));
		editAddExercises.add(jtfWorkoutQuantityLog);
		editAddExercises.add(new JLabel());
		editAddExercises.add(jbAddWorkoutLog);
		
		// -- Food/Recipes --
		cbRemoveFoodLog = new JComboBox();
		cbRemoveFoodLog.setPreferredSize(new Dimension(200, cbRemoveFoodLog.getPreferredSize().height));
		jbRemoveFoodLog	= new JButton("Remove");
		
		editDeleteFood.add(cbRemoveFoodLog, "North");
		editDeleteFood.add(jbRemoveFoodLog, "South");
		
		// -- Exercises/Workouts --
		cbRemoveExerciseLog = new JComboBox();
		cbRemoveExerciseLog.setPreferredSize(new Dimension(200, cbRemoveExerciseLog.getPreferredSize().height));
		jbRemoveExerciseLog	= new JButton("Remove");
		
		editDeleteExercises.add(cbRemoveExerciseLog, "North");
		editDeleteExercises.add(jbRemoveExerciseLog, "South");
		
		// -- Food/Recipes --
		jpEditFood.add(editAddFood, "North");
		jpEditFood.add(editDeleteFood, "South");
		
		// -- Exercises/Workouts --
		jpEditExercises.add(editAddExercises, "North");
		jpEditExercises.add(editDeleteExercises, "South");
		
		editSouth.add(cancelBtn);
		editSouth.add(saveLogBtn);
		
		editNorth.addTab("Initial Info", editInitial);
		editNorth.addTab("Food", jpEditFood);
		editNorth.addTab("Activity", jpEditExercises);
		
		editPanel.add(editNorth, "North");
		editPanel.add(editSouth, "South");
	}
	
	/**
	 * Builds the View panel. 
	 */
	private void buildViewPanel()
	{
		//this text area should display the current daily log, we should just
		//use the getDailyLog() method from the controller and paste information to the textArea
		viewNorth = new JPanel();
		
		jtaDisplayDailyLog = new JTextArea();
		jtaDisplayDailyLog.setWrapStyleWord(true);
		jtaDisplayDailyLog.setEditable(false);
		jtaDisplayDailyLog.setDisabledTextColor(Color.BLACK);
		
		JScrollPane jsp = new JScrollPane(jtaDisplayDailyLog);
		DefaultCaret caret = (DefaultCaret)jtaDisplayDailyLog.getCaret();
		caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
		
		viewChartBtn = new JButton("View Calorie Chart");
		viewEditBtn = new JButton("Edit");
		viewEditBtn.addActionListener(this);
		viewBackBtn = new JButton("Back");
		viewBackBtn.addActionListener(this);
		viewExportBtn = new JButton("Export...");
		viewExportBtn.addActionListener(this);
		
		viewNorth.add(viewChartBtn);
		viewNorth.add(viewEditBtn);
		viewNorth.add(viewBackBtn);
		viewNorth.add(viewExportBtn);
		viewPanel.add(viewNorth, "North");
		viewPanel.add(jsp, "Center");
	}
	
	/**
	 * Method that updates different components of the GUI. 
	 */
	@Override
	public void notifyObserver() {
		
		//updates the view section
		jtaDisplayDailyLog.setText(controller.getCurrDailyLog().toString() + "\nTotal calories for today: " + controller.getTotalCalories());
		
		//updates the edit section
		jtfWeight.setText("" + controller.getCurrDailyLog().getWeight());
		jtfCal.setText("" + controller.getCurrDailyLog().getLimit());
		
		//adding the curr daily logs date to the titled border
		javax.swing.border.TitledBorder tempBorder = (javax.swing.border.TitledBorder) editNorth.getBorder();
		tempBorder.setTitle("Daily Log - " + controller.getCurrDailyLog().getDate());
		
		Object[] foodList = controller.getCurrDailyLog().getIntake().keySet().toArray();
		
		//adds items to combobox which contains basic foods
		cbRemoveFoodLog.removeAllItems();
		for(int i = 0; i < foodList.length; i++)
			cbRemoveFoodLog.addItem((Food) foodList[i]);
		
		//adds items to combobox which contains recipe foods
		cbFoodNameLog.removeAllItems();
		for(int i = 0; i < controller.getBasicList().size(); i++)
			cbFoodNameLog.addItem(controller.getBasicList().get(i).getName());
		
		//adds items to combobox which contains recipe foods
		cbRecipeNameLog.removeAllItems();
		for(int i = 0; i < controller.getRecipeList().size(); i++)
			cbRecipeNameLog.addItem(controller.getRecipeList().get(i).getName());
		
		Object[] exerciseList = controller.getCurrDailyLog().getActivities().keySet().toArray();
		
		//adds items to combobox which contains basic exercises
		cbRemoveExerciseLog.removeAllItems();
		for(int i = 0; i < exerciseList.length; i++)
			cbRemoveExerciseLog.addItem((Activity) exerciseList[i]);
		
		//adds items to combobox which contains basic exercises
		cbExerciseNameLog.removeAllItems();
		for(int i = 0; i < controller.getBasicExerciseList().size(); i++)
			cbExerciseNameLog.addItem(controller.getBasicExerciseList().get(i).getName());
		
		//adds items to combobox which contains workouts
		cbWorkoutNameLog.removeAllItems();
		for(int i = 0; i < controller.getWorkoutList().size(); i++)
			cbWorkoutNameLog.addItem(controller.getWorkoutList().get(i).getName());
	}
	
	/**
	 * Checks if the input has commas or quote marks.
	 * @param input The input being tested
	 * @return True if the input does contains commas/quotemarks, false otherwise. 
	 */
	private boolean hasCommasOrQuotes(String input)
	{
		if(input.indexOf(",") != -1 || input.indexOf("\"") != -1)
			return true;
		else
			return false;
	}
}
